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

Ajoute la vue "mes groupes" à la page groupe #1080

Merged
merged 2 commits into from
Jul 1, 2021
Merged
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
255 changes: 239 additions & 16 deletions app/controllers/GroupController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import java.util.UUID

import actions.{LoginAction, RequestWithUserData}
import cats.syntax.all._
import constants.Constants
import Operators._
import javax.inject.{Inject, Singleton}
import models.{Area, Authorization, Organisation, UserGroup}
import models.formModels.{normalizedOptionalText, normalizedText}
import models.{Area, Authorization, Error, EventType, Organisation, User, UserGroup}
import models.formModels.{normalizedOptionalText, normalizedText, AddUserToGroupFormData}
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.data.Form
import play.api.data.Forms.{email, ignored, list, mapping, of, optional, text, uuid}
import play.api.data.validation.Constraints.maxLength
import play.api.mvc.{Action, AnyContent, InjectedController}
import play.api.i18n.I18nSupport
import play.api.mvc.{Action, AnyContent, Call, InjectedController, RequestHeader, Result}
import play.libs.ws.WSClient
import services._
import helper.BooleanHelper.not
Expand All @@ -34,9 +36,11 @@ import models.EventType.{
UserGroupEdited
}
import scala.concurrent.{ExecutionContext, Future}
import serializers.Keys

@Singleton
case class GroupController @Inject() (
applicationService: ApplicationService,
loginAction: LoginAction,
groupService: UserGroupService,
notificationService: NotificationService,
Expand All @@ -46,10 +50,176 @@ case class GroupController @Inject() (
userService: UserService
)(implicit ec: ExecutionContext, webJarsUtil: WebJarsUtil)
extends InjectedController
with I18nSupport
with Operators.Common
with GroupOperators
with UserOperators {

private val groupPageRedirectValue: String = "groupPage"

private def groupModificationOriginPage(implicit request: RequestHeader): (Boolean, Call) =
(
request.getQueryString(Keys.QueryParam.redirect),
request.getQueryString(Keys.QueryParam.groupId)
) match {
case (Some(`groupPageRedirectValue`), Some(groupId)) =>
(true, routes.GroupController.editGroup(UUID.fromString(groupId)))
case _ =>
(false, routes.GroupController.showEditMyGroups)
}

def addToGroup(groupId: UUID) =
addOrRemoveUserAction(groupId) { implicit request =>
val (originIsGroupPage, redirectPage) = groupModificationOriginPage
AddUserToGroupFormData.form
.bindFromRequest()
.fold(
err => {
val message = "L’adresse email n'est pas correcte"
eventService.log(EventType.AddUserToGroupBadUserInput, message)
if (originIsGroupPage) withGroup(groupId)(group => editGroupPage(group, err))
else editMyGroupsPage(err)
},
data =>
userService
.byEmailFuture(data.email)
.zip(userService.byGroupIdsFuture(List(groupId), includeDisabled = true))
.flatMap {
case (None, _) =>
eventService.log(
EventType.AddUserToGroupBadUserInput,
s"Tentative d'ajout de l'utilisateur inexistant ${data.email} au groupe $groupId"
)
Future.successful(
Redirect(redirectPage)
.flashing("error" -> "L’utilisateur n’existe pas dans Administration+")
)
case (Some(userToAdd), usersInGroup)
if usersInGroup.map(_.id).contains[UUID](userToAdd.id) =>
eventService.log(
EventType.AddUserToGroupBadUserInput,
s"Tentative d'ajout de l'utilisateur ${userToAdd.id} déjà présent au groupe $groupId",
involvesUser = userToAdd.id.some
)
Future.successful(
Redirect(redirectPage)
.flashing("error" -> "L’utilisateur est déjà présent dans le groupe")
)
case (Some(userToAdd), _) =>
userService
.addToGroup(userToAdd.id, groupId)
.map { _ =>
eventService.log(
EventType.UserGroupEdited,
s"Utilisateur ${userToAdd.id} ajouté au groupe $groupId",
involvesUser = userToAdd.id.some
)
Redirect(redirectPage)
.flashing("success" -> "L’utilisateur a été ajouté au groupe")
}
}
)
}

def enableUser(userId: UUID) =
loginAction.async { implicit request =>
val (_, redirectPage) = groupModificationOriginPage
withUser(
userId,
includeDisabled = true,
errorMessage = s"L'utilisateur $userId n'existe pas et ne peut pas être réactivé",
errorResult = Redirect(redirectPage)
.flashing(
"error" -> ("L’utilisateur n’existe pas dans Administration+. " +
"S’il s’agit d’une erreur, vous pouvez contacter le support.")
)
.some
) { otherUser =>
asUserWithAuthorization(Authorization.canEnableOtherUser(otherUser))(() =>
(
EventType.EditUserUnauthorized,
s"L'utilisateur n'est pas autorisé à réactiver l'utilisateur $userId"
)
) { () =>
userService
.enable(userId)
.map(
_.fold(
error => {
eventService.logError(error)
Redirect(redirectPage).flashing("error" -> Constants.error500FlashMessage)
},
_ => {
eventService.log(
EventType.UserEdited,
s"Utilisateur $userId réactivé",
involvesUser = userId.some
)
Redirect(redirectPage)
.flashing("success" -> "L’utilisateur a bien été réactivé.")
}
)
)
}
}
}

def removeFromGroup(userId: UUID, groupId: UUID) =
addOrRemoveUserAction(groupId) { implicit request =>
val (_, redirectPage) = groupModificationOriginPage
withUser(
userId,
includeDisabled = true,
errorMessage = s"L'utilisateur $userId n'existe pas et ne peut pas être désactivé",
errorResult = Redirect(redirectPage)
.flashing(
"error" -> ("L’utilisateur n’existe pas dans Administration+. " +
"S’il s’agit d’une erreur, vous pouvez contacter le support.")
)
.some
) { otherUser =>
val result: Future[Either[Error, Result]] =
if (otherUser.groupIds.toSet.size <= 1) {
userService
.disable(userId)
.map(_.map { _ =>
eventService.log(
EventType.UserEdited,
s"Utilisateur $userId désactivé",
involvesUser = userId.some
)
Redirect(redirectPage).flashing("success" -> "L’utilisateur a bien été désactivé.")
})
} else {
userService
.removeFromGroup(userId, groupId)
.map(_.map { _ =>
eventService.log(
EventType.UserGroupEdited,
s"Utilisateur $userId retiré du groupe $groupId",
involvesUser = userId.some
)
Redirect(redirectPage)
.flashing("success" -> "L’utilisateur a bien été retiré du groupe.")
})
}
result.map(
_.fold(
error => {
eventService.logError(error)
Redirect(redirectPage).flashing("error" -> Constants.error500FlashMessage)
},
identity
)
)
}
}

def showEditMyGroups =
loginAction.async { implicit request =>
editMyGroupsPage(AddUserToGroupFormData.form)
}

def deleteUnusedGroupById(groupId: UUID): Action[AnyContent] =
loginAction.async { implicit request =>
withGroup(groupId) { group: UserGroup =>
Expand Down Expand Up @@ -88,18 +258,7 @@ case class GroupController @Inject() (
),
Unauthorized("Vous ne pouvez pas éditer ce groupe : êtes-vous dans la bonne zone ?").some
) { () =>
val groupUsers = userService.byGroupIds(List(id), includeDisabled = true)
eventService.log(EditGroupShowed, s"Visualise la vue de modification du groupe")
val isEmpty = groupService.isGroupEmpty(group.id)
Future(
Ok(
views.html.editGroup(request.currentUser, request.rights)(
group,
groupUsers,
isEmpty
)
)
)
editGroupPage(group, AddUserToGroupFormData.form)
}
}
}
Expand Down Expand Up @@ -208,7 +367,71 @@ case class GroupController @Inject() (
}
}

def addGroupForm[A](timeZone: ZoneId)(implicit request: RequestWithUserData[A]) =
private def addOrRemoveUserAction(
groupId: UUID
)(inner: RequestWithUserData[_] => Future[Result]): Action[AnyContent] =
loginAction.async { implicit request =>
asUserWithAuthorization(Authorization.canAddOrRemoveOtherUser(groupId))(
() =>
(
EventType.EditGroupUnauthorized,
s"L'utilisateur n'est pas autorisé à éditer le groupe $groupId"
), {
val message = "Vous n’avez pas le droit de modifier ce groupe"
Redirect(routes.GroupController.showEditMyGroups).flashing("error" -> message).some
}
)(() => inner(request))
}

private def editMyGroupsPage(
addUserForm: Form[AddUserToGroupFormData]
)(implicit request: RequestWithUserData[_]): Future[Result] =
for {
groups <- groupService.byIdsFuture(request.currentUser.groupIds)
users <- userService.byGroupIdsFuture(groups.map(_.id), includeDisabled = true)
applications <- applicationService.allForUserIds(users.map(_.id))
} yield {
eventService.log(EventType.EditMyGroupShowed, "Visualise la modification de ses groupes")
Ok(
views.editMyGroups
.page(
request.currentUser,
request.rights,
addUserForm,
groups,
users,
applications,
identity
)
)
}

private def editGroupPage(group: UserGroup, addUserForm: Form[AddUserToGroupFormData])(implicit
request: RequestWithUserData[_]
): Future[Result] = {
val groupUsers = userService.byGroupIds(List(group.id), includeDisabled = true)
eventService.log(EditGroupShowed, s"Visualise la vue de modification du groupe")
val isEmpty = groupService.isGroupEmpty(group.id)
applicationService
.allForUserIds(groupUsers.map(_.id))
.map(applications =>
Ok(
views.html.editGroup(request.currentUser, request.rights)(
group,
groupUsers,
isEmpty,
applications,
addUserForm,
url =>
(url + "?" +
Keys.QueryParam.redirect + "=" + groupPageRedirectValue + "&" +
Keys.QueryParam.groupId + "=" + group.id.toString)
)
)
)
}

private def addGroupForm[A](timeZone: ZoneId)(implicit request: RequestWithUserData[A]) =
Form(
mapping(
"id" -> ignored(UUID.randomUUID()),
Expand Down
8 changes: 4 additions & 4 deletions app/controllers/Operators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ object Operators {
groupId: UUID
)(
payload: UserGroup => Future[Result]
)(implicit request: RequestWithUserData[AnyContent], ec: ExecutionContext): Future[Result] =
)(implicit request: RequestWithUserData[_], ec: ExecutionContext): Future[Result] =
groupService
.groupById(groupId)
.fold({
Expand All @@ -52,7 +52,7 @@ object Operators {

def asAdminOfGroupZone(group: UserGroup)(event: () => (EventType, String))(
payload: () => Future[Result]
)(implicit request: RequestWithUserData[AnyContent], ec: ExecutionContext): Future[Result] =
)(implicit request: RequestWithUserData[_], ec: ExecutionContext): Future[Result] =
if (not(request.currentUser.admin)) {
val (eventType, description) = event()
eventService.log(eventType, description = description)
Expand Down Expand Up @@ -174,8 +174,8 @@ object Operators {
def applicationService: ApplicationService
def eventService: EventService

private def manageApplicationError[A](applicationId: UUID, error: Error)(implicit
request: RequestWithUserData[A],
private def manageApplicationError(applicationId: UUID, error: Error)(implicit
request: RequestWithUserData[_],
ec: ExecutionContext
): Future[Result] = {
val result =
Expand Down
Loading