Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Community] Enhanced team and role management #2567

Open
wants to merge 3 commits into
base: 14.0
Choose a base branch
from
Open
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
13 changes: 10 additions & 3 deletions src/main/community/Controller/TeamController.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public function getIgnore(): array

/**
* @Route("/workspace/{id}/teams", name="apiv2_workspace_team_list", methods={"GET"})
*
* @EXT\ParamConverter("workspace", class="Claroline\CoreBundle\Entity\Workspace\Workspace", options={"mapping": {"id": "uuid"}})
*/
public function listByWorkspaceAction(Workspace $workspace, Request $request): JsonResponse
Expand All @@ -83,16 +84,18 @@ public function listByWorkspaceAction(Workspace $workspace, Request $request): J

/**
* @Route("/{id}/users/{role}", name="apiv2_team_list_users", methods={"GET"})
*
* @EXT\ParamConverter("team", class="Claroline\CommunityBundle\Entity\Team", options={"mapping": {"id": "uuid"}})
* @EXT\ParamConverter("user", converter="current_user", options={"allowAnonymous"=true})
*/
public function listUsersAction(Team $team, string $role, User $user, Request $request): JsonResponse
{
$this->checkPermission('OPEN', $team, [], true);

$hiddenFilters = [
'role' => ['manager' === $role ? $team->getManagerRole()->getUuid() : $team->getRole()->getUuid()],
];
$hiddenFilters = [];

$role = 'manager' === $role ? $team->getManagerRole() : $team->getRole();
$hiddenFilters['role'] = $role?->getUuid();

if (!$this->checkPermission('ROLE_ADMIN')) {
// only list users for the current user organizations
Expand All @@ -110,6 +113,7 @@ public function listUsersAction(Team $team, string $role, User $user, Request $r

/**
* @Route("/{id}/users/{role}", name="apiv2_team_register", methods={"PATCH"})
*
* @EXT\ParamConverter("team", class="Claroline\CommunityBundle\Entity\Team", options={"mapping": {"id": "uuid"}})
*/
public function registerAction(Team $team, string $role, Request $request): JsonResponse
Expand Down Expand Up @@ -147,6 +151,7 @@ public function registerAction(Team $team, string $role, Request $request): Json

/**
* @Route("/{id}/users/{role}", name="apiv2_team_unregister", methods={"DELETE"})
*
* @EXT\ParamConverter("team", class="Claroline\CommunityBundle\Entity\Team", options={"mapping": {"id": "uuid"}})
*/
public function unregisterAction(Team $team, string $role, Request $request): JsonResponse
Expand All @@ -166,6 +171,7 @@ public function unregisterAction(Team $team, string $role, Request $request): Js

/**
* @Route("/{id}/register", name="apiv2_team_self_register", methods={"PUT"})
*
* @EXT\ParamConverter("team", class="Claroline\CommunityBundle\Entity\Team", options={"mapping": {"id": "uuid"}})
* @EXT\ParamConverter("user", converter="current_user", options={"allowAnonymous"=false})
*/
Expand Down Expand Up @@ -195,6 +201,7 @@ public function selfRegisterAction(Team $team, User $user): JsonResponse

/**
* @Route("/{id}/unregister", name="apiv2_team_self_unregister", methods={"DELETE"})
*
* @EXT\ParamConverter("team", class="Claroline\CommunityBundle\Entity\Team", options={"mapping": {"id": "uuid"}})
* @EXT\ParamConverter("user", converter="current_user", options={"allowAnonymous"=false})
*/
Expand Down
33 changes: 28 additions & 5 deletions src/main/community/Entity/Team.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

/**
* @ORM\Table(name="claro_team")
*
* @ORM\Entity(repositoryClass="Claroline\CommunityBundle\Repository\TeamRepository")
*/
class Team
Expand All @@ -39,14 +40,16 @@ class Team

/**
* @ORM\ManyToOne(targetEntity="Claroline\CoreBundle\Entity\Workspace\Workspace")
*
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
*
* @var Workspace
*/
private $workspace;

/**
* @ORM\OneToOne(targetEntity="Claroline\CoreBundle\Entity\Role", cascade={"remove"})
* @ORM\OneToOne(targetEntity="Claroline\CoreBundle\Entity\Role")
*
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
*
* @var Role
Expand All @@ -55,14 +58,16 @@ class Team

/**
* @ORM\ManyToMany(targetEntity="Claroline\CoreBundle\Entity\User")
*
* @ORM\JoinTable(name="claro_team_users")
*
* @var ArrayCollection|User[]
*/
private $users;

/**
* @ORM\OneToOne(targetEntity="Claroline\CoreBundle\Entity\Role", cascade={"remove"})
* @ORM\OneToOne(targetEntity="Claroline\CoreBundle\Entity\Role")
*
* @ORM\JoinColumn(name="manager_role_id", nullable=true, onDelete="SET NULL")
*
* @var Role
Expand Down Expand Up @@ -92,6 +97,7 @@ class Team

/**
* @ORM\OneToOne(targetEntity="Claroline\CoreBundle\Entity\Resource\ResourceNode")
*
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
*
* @var ResourceNode
Expand All @@ -105,6 +111,13 @@ class Team
*/
private $isPublic = false;

/**
* @ORM\Column(name="is_using_existing_roles", type="boolean")
*
* @var bool
*/
private $isUsingExistingRoles = false;

/**
* @ORM\Column(name="dir_deletable", type="boolean", options={"default" = 0})
*
Expand Down Expand Up @@ -171,7 +184,7 @@ public function getManagerRole(): ?Role
return $this->managerRole;
}

public function setManagerRole(?Role $managerRole = null): void
public function setManagerRole(Role $managerRole = null): void
{
$this->managerRole = $managerRole;
}
Expand All @@ -181,7 +194,7 @@ public function getMaxUsers(): ?int
return $this->maxUsers;
}

public function setMaxUsers(?int $maxUsers = null): void
public function setMaxUsers(int $maxUsers = null): void
{
$this->maxUsers = $maxUsers;
}
Expand Down Expand Up @@ -211,7 +224,7 @@ public function getDirectory(): ?ResourceNode
return $this->directory;
}

public function setDirectory(?ResourceNode $directory = null)
public function setDirectory(ResourceNode $directory = null)
{
$this->directory = $directory;
}
Expand All @@ -235,4 +248,14 @@ public function setDirDeletable(bool $dirDeletable): void
{
$this->dirDeletable = $dirDeletable;
}

public function isUsingExistingRoles(): bool
{
return $this->isUsingExistingRoles;
}

public function setIsUsingExistingRoles(bool $isUsingExistingRoles): void
{
$this->isUsingExistingRoles = $isUsingExistingRoles;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Claroline\CommunityBundle\Installation\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated migration based on mapping information: modify it with caution.
*
* Generation date: 2023/08/23 12:02:36
*/
final class Version20230823120235 extends AbstractMigration
{
public function up(Schema $schema): void
{
$this->addSql('
ALTER TABLE claro_team
ADD is_using_existing_roles TINYINT(1) NOT NULL
');
$this->addSql('
ALTER TABLE claro_team
DROP FOREIGN KEY FK_A2FE5804D60322AC
');
$this->addSql('
ALTER TABLE claro_team
DROP INDEX UNIQ_A2FE5804D60322AC
');
$this->addSql('
ALTER TABLE claro_team
DROP FOREIGN KEY FK_A2FE580468CE17BA
');
$this->addSql('
ALTER TABLE claro_team
DROP INDEX UNIQ_A2FE580468CE17BA
');
}

public function down(Schema $schema): void
{
$this->addSql('
ALTER TABLE claro_team
DROP is_using_existing_roles
');
$this->addSql('
ALTER TABLE claro_team
ADD CONSTRAINT FK_A2FE5804D60322AC FOREIGN KEY (role_id)
REFERENCES claro_role (id)
ON DELETE SET NULL
');
$this->addSql('
ALTER TABLE claro_team
ADD UNIQUE INDEX UNIQ_A2FE5804D60322AC (role_id)
');
$this->addSql('
ALTER TABLE claro_team
ADD CONSTRAINT FK_A2FE580468CE17BA FOREIGN KEY (manager_role_id)
REFERENCES claro_role (id)
ON DELETE SET NULL
');
$this->addSql('
ALTER TABLE claro_team
ADD UNIQUE INDEX UNIQ_A2FE580468CE17BA (manager_role_id)
');
}
}
18 changes: 10 additions & 8 deletions src/main/community/Manager/TeamManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,21 +95,23 @@ public function createTeamRole(Team $team, ?bool $isManager = false): Role

public function deleteTeamRoles(Team $team): void
{
if (!empty($team->getRole())) {
$this->om->remove($team->getRole());
}
if (!$team->isUsingExistingRoles()) {
if (!empty($team->getRole())) {
$this->om->remove($team->getRole());
}

if (!empty($team->getManagerRole())) {
$this->om->remove($team->getManagerRole());
}
if (!empty($team->getManagerRole())) {
$this->om->remove($team->getManagerRole());
}

$this->om->flush();
$this->om->flush();
}
}

/**
* Creates team directory.
*/
public function createTeamDirectory(Team $team, User $user, ?ResourceNode $resource = null, ?array $creatableResources = []): Directory
public function createTeamDirectory(Team $team, User $user, ResourceNode $resource = null, ?array $creatableResources = []): Directory
{
$workspace = $team->getWorkspace();

Expand Down
37 changes: 37 additions & 0 deletions src/main/community/Resources/modules/team/components/form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,43 @@ const TeamFormComponent = props =>
}
}
]
}, {
icon: 'fa fa-fw fa-chess',
title: trans('roles'),
fields: [{
name: 'isUsingExistingRoles',
type: 'boolean',
label: trans('use_existing_roles', {}, 'community'),
help: trans('use_existing_roles_help', {}, 'community'),
onChange: (value) => {
if (!value) {
props.updateProp('role', null)
props.updateProp('managerRole', null)
}
}
}, {
name: 'role',
type: 'role',
label: trans('role', {}, 'community'),
displayed: (team) => team.isUsingExistingRoles,
options: team => ({
picker: {
url: ['apiv2_workspace_list_roles', {id: get(team, 'workspace.id', null)}],
filters: []
}
})
}, {
name: 'managerRole',
type: 'role',
label: trans('manager_role', {}, 'community'),
displayed: (team) => team.isUsingExistingRoles,
options: team => ({
picker: {
url: ['apiv2_workspace_list_roles', {id: get(team, 'workspace.id', null)}],
filters: []
}
})
}]
}, {
icon: 'fa fa-fw fa-desktop',
title: trans('display_parameters'),
Expand Down
1 change: 1 addition & 0 deletions src/main/community/Resources/modules/team/prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const Team = {
managerRole: T.shape(
RoleTypes.propTypes
),
isUsingExistingRoles: T.bool.isRequired,
directory: T.shape(
ResourceNodeTypes.propTypes
)
Expand Down
2 changes: 2 additions & 0 deletions src/main/community/Resources/translations/community.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
"delete_team_directory": "Delete team's directory at team deletion",
"team_creatable_resources": "Resources that can be created by users",
"team_default_resource": "Default resource",
"use_existing_roles": "Use existing roles",
"use_existing_roles_help": "If enabled, existing roles will be used for teams. Otherwise, team-specific roles will be created.",

"user": "User",
"users": "Users",
Expand Down
2 changes: 2 additions & 0 deletions src/main/community/Resources/translations/community.fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
"delete_team_directory": "Supprimer le dossier à la suppression de l'équipe",
"team_creatable_resources": "Ressources pouvant être créées par les utilisateurs",
"team_default_resource": "Ressource par défaut",
"use_existing_roles": "Utiliser des rôles existants",
"use_existing_roles_help": "Si activé, des rôles existants seront utilisés pour les équipes. Sinon, des rôles spécifiques aux équipes seront créés.",

"user": "Utilisateur",
"users": "Utilisateurs",
Expand Down
2 changes: 2 additions & 0 deletions src/main/community/Serializer/TeamSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public function serialize(Team $team, array $options = []): array
'name' => $team->getName(),
'thumbnail' => $team->getThumbnail(),
'poster' => $team->getPoster(),
'isUsingExistingRoles' => $team->isUsingExistingRoles(),
'users' => $this->om->getRepository(Team::class)->countUsers($team),
'meta' => [
'description' => $team->getDescription(),
Expand Down Expand Up @@ -127,6 +128,7 @@ public function deserialize(array $data, Team $team, array $options = []): Team
$this->sipe('publicDirectory', 'setPublic', $data, $team);
$this->sipe('deletableDirectory', 'setDirDeletable', $data, $team);
$this->sipe('restrictions.users', 'setMaxUsers', $data, $team);
$this->sipe('isUsingExistingRoles', 'setIsUsingExistingRoles', $data, $team);

if (isset($data['directory'])) {
/** @var ResourceNode $directoryNode */
Expand Down
Loading